from PyQt5.QtWidgets import QMessageBox, QFileDialog
from PyQt5 import QtCore
from egfunc.designrs import designRs, designRsFre  # 设计谱函数
import numpy as np

"================地震影响系数曲线生成界面====================="


class Coe_Generator:
    """
    地震影响系数曲线生成模块功能类
    """

    def __init__(self, ui, ui_class, father):
        """
        初始化
        :param ui:
        :param ui_class:
        :param father:
        """
        self.UI_widget = ui
        self.COEUI = ui_class
        self.father = father

        self.cd = 0  # 场地类型 0~4
        self.ld = 0  # 地震烈度 6 7 7.5 8 8.25 8.5 9 10 对应0-7
        self.fz = 1  # 场地分组 1~3
        self.rare = 'basic'  # 0多遇地震 1罕遇地震  影响特征周期
        self.Damp = 0.05  # 阻尼比
        "=========构造反应谱横坐标序列========="
        f1 = np.arange(0.15, 3, 0.05)
        f2 = np.arange(3, 3.6, 0.15)
        f3 = np.arange(3.6, 5, 0.2)
        f4 = np.arange(5, 8, 0.25)
        f5 = np.arange(8, 15, 0.5)
        f6 = np.arange(15, 34, 1)
        self.f = np.concatenate((f1, f2, f3, f4, f5, f6))
        # 反应谱频率范围：0.15-33Hz
        self.Tyz = np.sort(1. / self.f)  # 反应谱横坐标  非均匀
        self.nTyz = len(self.Tyz)  # 特征周期点个数

        self.sjp = np.zeros(self.nTyz)  # 设计谱点数为nTyz
        self.unit = "周期(s)"
        self.refresh()
        "============禁止缩放窗口============="
        # self.UI_widget.setMaximumSize(800, 600)
        # self.UI_widget.setMinimumSize(800, 600)
        self.UI_widget.setFixedSize(800, 600)
        # self.UI_widget.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        self.UI_widget.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint | QtCore.Qt.WindowCloseButtonHint)

        self.COEUI.comboBox_cd.currentIndexChanged[str].connect(self.set_cd)  # 场地类型按钮
        self.COEUI.comboBox_ld.currentIndexChanged[str].connect(self.set_ld)  # 烈度按钮
        self.COEUI.comboBox_fz.currentIndexChanged[str].connect(self.set_fz)  # 分组按钮
        self.COEUI.comboBox_rare.currentIndexChanged[str].connect(self.set_rare)  # 罕见度按钮
        self.COEUI.comboBox_unit.currentIndexChanged[str].connect(self.set_unit)  # 设置横坐标  周期/频率

        self.COEUI.lineEdit_Damp.editingFinished.connect(self.input_Damp)  # 阻尼比设置框
        self.COEUI.QSlider_Damp.sliderMoved.connect(self.set_Damp)  # 阻尼比设置 滚动条

        self.COEUI.output.clicked.connect(self.output)  # 导出数据按钮
        self.COEUI.quit.clicked.connect(self.quit)  # 退出
        # 反应谱画布
        self.COEUI.graph_fyp.setBackground('w')
        self.COEUI.graph_fyp.setTitle("地震影响系数曲线", color='000080', size='12pt')
        self.COEUI.graph_fyp.setLabel("bottom", "周期(s)", color='b')
        self.COEUI.graph_fyp.enableAutoRange('xy', True)
        self.COEUI.graph_fyp.showGrid(True, True)

        # 按钮美化
        self.COEUI.output.setStyleSheet("QPushButton{font: 20pt '楷体'}"
                                        "QPushButton{color:black}"
                                        "QPushButton:hover{color:red}"
                                        "QPushButton{background-color:rgb(0,255,255)}"
                                        "QPushButton{border:2px}"
                                        "QPushButton{border-radius:10px}"
                                        "QPushButton{padding:2px 4px}")

        self.COEUI.quit.setStyleSheet("QPushButton{font: 20pt '楷体'}"
                                      "QPushButton{color:black}"
                                      "QPushButton:hover{color:red}"
                                      "QPushButton{background-color:rgb(233,255,211)}"
                                      "QPushButton{border:2px}"
                                      "QPushButton{border-radius:10px}"
                                      "QPushButton{padding:2px 4px}")

    def refresh(self):
        """
        刷新
        :return:
        """
        self.COEUI.graph_fyp.clear()  # 清除之前的图像
        """=================计算设计谱================"""
        if self.unit == "周期(s)":
            for i in range(self.nTyz):  # 得到一定场地条件下的设计谱
                self.sjp[i] = designRs(self.Tyz[i], self.Damp, self.ld, self.cd, self.fz, self.rare)
            self.COEUI.graph_fyp.enableAutoRange('xy', True)
            self.COEUI.graph_fyp.setLabel("bottom", "周期(s)", color='b')
            self.COEUI.graph_fyp.plot(self.Tyz, self.sjp, pen='k')
        else:
            for i in range(self.nTyz):  # 得到一定场地条件下的设计谱
                self.sjp[i] = designRsFre(self.Tyz[i], self.Damp, self.ld, self.cd, self.fz, self.rare)
            self.COEUI.graph_fyp.enableAutoRange('xy', True)
            self.COEUI.graph_fyp.setLabel("bottom", "频率(Hz)", color='b')
            self.COEUI.graph_fyp.plot(self.f, np.flipud(self.sjp), pen='k')

    def set_cd(self, i):  # 没法获得index值，信号返回的是当前被选择的内容，导致分类比较繁琐
        """
        设置场地类型
        :param i:
        :return:
        """
        if i == 'Ⅰ(0)':
            self.cd = 0
        elif i == 'Ⅰ(1)':
            self.cd = 1
        elif i == 'Ⅱ':
            self.cd = 2
        elif i == 'Ⅲ':
            self.cd = 3
        elif i == 'Ⅳ':
            self.cd = 4
        print('场地类型为：%s' % i)

        self.refresh()

    def set_ld(self, i):
        """
        设置烈度
        :param i:
        :return:
        """
        if i == '6(0.05g)':
            self.ld = 0
        elif i == '7(0.10g)':
            self.ld = 1
        elif i == '7(0.15g)':
            self.ld = 2
        elif i == '8(0.20g)':
            self.ld = 3
        elif i == '8(0.25g)':
            self.ld = 4
        elif i == '8(0.30g)':
            self.ld = 5
        elif i == '9(0.40g)':
            self.ld = 6
        elif i == '10(0.50g)':
            self.ld = 7
        print('烈度：%s' % i)
        self.refresh()

    def set_fz(self, i):
        """
        设置分组
        :param i:
        :return:
        """
        self.fz = int(i)
        print('分组：%s' % i)
        self.refresh()

    def set_rare(self, i):
        """
        设置地震罕见度
        :param i:
        :return:
        """
        if i == '基本地震动':
            self.rare = 'basic'
            print('基本地震动')

        elif i == '罕遇地震动':
            self.rare = 'rare'
            print('罕遇地震动')

        elif i == '多遇地震动':
            self.rare = 'frequent'
            print('多遇地震动')

        elif i == '极罕遇地震动':
            self.rare = 'very rare'
            print('极罕遇地震动')
        self.refresh()

    def set_Damp(self):
        """
        设置阻尼比
        :return:
        """
        self.Damp = np.round(self.COEUI.QSlider_Damp.value() * 0.005, 5)

        print(self.Damp)
        self.COEUI.lineEdit_Damp.setText(str(self.Damp))
        self.refresh()

    def input_Damp(self):
        """
        输入阻尼比
        :return:
        """
        try:
            self.Damp = float(self.COEUI.lineEdit_Damp.text())  # float确保输入的是浮点小数
            if self.Damp < 0 or self.Damp > 1:  # 超界，设置默认值
                self.Damp = 0.05
                self.COEUI.lineEdit_Damp.setText('0.05')
                self.COEUI.lineEdit_Damp.setPlaceholderText('0.05')
                self.refresh()
                QMessageBox.warning(self.UI_widget, '错误', '阻尼比应取0~1之间的数！\n请重新输入！', QMessageBox.Yes)

                return
            else:  # 正常
                print('阻尼比：%s' % self.Damp)
                self.COEUI.QSlider_Damp.setValue(int(self.Damp / 0.005))

        except ValueError:
            print('参数错误')
            print('阻尼比设置为默认值0.05')
            self.Damp = 0.05
            self.COEUI.lineEdit_Damp.setText('0.05')
            self.COEUI.lineEdit_Damp.setPlaceholderText('0.05')

        self.refresh()

    def set_unit(self, i):
        """
        设置横坐标
        :param i:
        :return:
        """
        self.unit = i
        print("横坐标：%s" % i)
        self.refresh()

    def output(self):
        """
        数据导出函数
        """
        # 路径选择
        filePath, file_type = QFileDialog.getSaveFileName(
            self.UI_widget,  # 父窗口对象
            "选择要保存的文件",  # 标题
            r"d:\\data",  # 起始目录
            "Text Files(*.txt);;Excel Files(*.xls);;Excel Files(*.xlsx)")  # 选择类型过滤项，过滤内容在括号中
        if self.unit == "周期(s)":
            x = self.Tyz
            y = self.sjp
        else:
            x = self.f
            y = np.flipud(self.sjp)
        # 合成一个ndarray
        if file_type:
            with open(filePath, 'w') as file:
                z = np.concatenate((x.reshape(len(x), 1), y.reshape(len(y), 1)), axis=1)
                if self.unit == "周期(s)":
                    np.savetxt(file, z, fmt="%.6f\t          %.6f\t",
                               header="地震影响系数曲线\n"
                                      "场地类型：      {0}\n"
                                      "地震烈度：       {1}\n"
                                      "设计地震分组：{2}\n"
                                      "地震罕见度：   {3}\n"
                                      "阻尼比：          {4}\n"
                                      "周期(s)          影响系数"
                               .format(self.COEUI.comboBox_cd.currentText(),
                                       self.COEUI.comboBox_ld.currentText(),
                                       self.COEUI.comboBox_fz.currentText(),
                                       self.COEUI.comboBox_rare.currentText(),
                                       self.Damp))
                else:
                    np.savetxt(file, z, fmt="%.2f\t            %.6f\t",
                               header="地震影响系数曲线\n"
                                      "场地类型：      {0}\n"
                                      "地震烈度：       {1}\n"
                                      "设计地震分组：{2}\n"
                                      "地震罕见度：   {3}\n"
                                      "阻尼比：          {4}\n"
                                      "频率(Hz)   影响系数"
                               .format(self.COEUI.comboBox_cd.currentText(),
                                       self.COEUI.comboBox_ld.currentText(),
                                       self.COEUI.comboBox_fz.currentText(),
                                       self.COEUI.comboBox_rare.currentText(),
                                       self.Damp))
            file.close()
            QMessageBox.information(self.UI_widget, '成功', '数据成功导出！', QMessageBox.Yes)
        # 未选择输出
        else:
            QMessageBox.information(self.UI_widget, '提示', '数据未导出！', QMessageBox.Yes)

    def quit(self):
        """
        退出界面
        :return:
        """
        print("已退出地震影响系数曲线生成模块！")
        self.UI_widget.close()
        self.father.show()
